home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / UUPC3 / (MAIL__) / MAIL.C < prev    next >
C/C++ Source or Header  |  1991-07-24  |  13KB  |  653 lines

  1. /*
  2.  * mail.c
  3.  */
  4.  
  5. #include <stdio.h>
  6. #ifdef THINK_C
  7. # include <console.h>
  8. #endif THINK_C
  9. #include "host.h"
  10.  
  11. #define exit return
  12.  
  13. FILE *FOPEN();
  14. FILE *freopen();
  15.  
  16. #define LSIZE    256
  17.  
  18. static char linebuf[LSIZE];
  19. static char resp[LSIZE];
  20.  
  21. static char mfilename[132];
  22.  
  23. struct ldesc {
  24.    int    delete;  /* status of this message */
  25.    long  adr;  /* address of From line */
  26.    long  Date;  /* address of Date: line */
  27.    long  subject; /* address of Subject: line */
  28.    long  from;  /* address of From: line */
  29.    long  size;  /* number of lines */
  30. };
  31.  
  32. struct ldesc letters[300];
  33.  
  34. int    letternum   = 0;
  35. char    thefilename[50];
  36.  
  37. char    tmailbox[64];
  38. char  tmailbag[64];
  39.  
  40.  
  41. FILE    *fmailbox;
  42. FILE  *rmailbox;
  43. FILE *fmailbag;
  44.  
  45. int error = 0;
  46. int modified;
  47.  
  48. int printonly;
  49.  
  50. int PageCount = 0;
  51.  
  52. mailmain(argc, argv)
  53. char **argv;
  54. {
  55.  
  56.  /* HOSTINIT;
  57.  loadenv(); */
  58.  
  59.  mkfilename( tmailbox, tempdir, "mailbox");
  60.  mkfilename( tmailbag, tempdir, "mailbag");
  61.  
  62.  unlink( tmailbox );
  63.  
  64.  if ( mailbox == (char *)NULL )
  65.   strcpy(mailbox,"???");
  66.  
  67.  if ( argc == 1 ||
  68.   ( argv[1][0] == '-' ) && ( argv[1][1] != 's' ))
  69.   showmail (argc, argv );
  70.  else
  71.   lmail (argc, argv );
  72.  
  73.  finis();
  74.  
  75. }
  76.  
  77. finis()
  78. {
  79.  if ( fmailbag != (FILE *)NULL) fclose( fmailbag );
  80.  unlink( tmailbox );
  81.  unlink( tmailbag );
  82.  exit( error );
  83. }
  84.  
  85. /* sendmail
  86.  send message n to "line"
  87. */
  88. sendmail(n, line)
  89.  char *line; {
  90.  char  *argv[50];
  91.  int  argc;
  92.  char buf[BUFSIZ];
  93.  long  bytes;
  94.  
  95.  /* open a temporary file */
  96.  fmailbag = FOPEN( tmailbag, "w", 'b' );
  97.  
  98.  /* copy nth message to mailbag file */
  99.  fseek( fmailbox, letters[ n ].adr, 0 );
  100.  bytes = letters[ n+1 ].adr - letters[ n ].adr;
  101.  
  102.  while( bytes > 0 && fgets( buf, BUFSIZ, fmailbox) ) {
  103.   fputs( buf, fmailbag  );
  104.   bytes -= strlen( buf );
  105.  }
  106.  
  107.  fclose( fmailbag );
  108.  
  109.  /* use mailbag as stdin to mail delivery */
  110.  fclose( stdin );
  111.  FILEMODE( 'b' );
  112.  if(freopen(tmailbag, "r", stdin) != (FILE *)NULL) {
  113.   argc = getargs(line, argv);
  114.   lmail(argc, argv);
  115.   fclose(stdin);
  116.  }
  117.  
  118. #ifdef MSDOS
  119.  FILEMODE( 't' );
  120.  freopen( CONSOLE, "r", stdin );
  121. #else
  122. # ifndef THINK_C
  123.  /* I don't know how this line following could ever
  124.   * produce the correct results - device is "modem" here
  125.   * not even /dev/tty for UNIX A. Shapiro 11/21/89
  126.   */
  127.  freopen( device, "r", stdin );
  128. # else THINK_C
  129.  /* opening a new console is NOT what is required here since
  130.   * the old stdout is still attached to the old console.
  131.   * Still if we get this far we'd better have something
  132.   * from which to issue the 'q'. (hope this code is never reached
  133.   * since the 'f' option was turned off.)
  134.   * A. Shapiro 11/21/89
  135.   */
  136.  freopenc((FILE *)NULL, stdin);
  137.  csetmode(C_ECHO, stdin);
  138. # endif THINK_C
  139. #endif
  140.  
  141.  /* get rid of mailbag */
  142.  unlink( tmailbag );
  143. }
  144.  
  145.  
  146. linvert( i )
  147. int i;
  148. {
  149.  return( letternum - i - 1 );
  150. }
  151.  
  152. showmail(argc, argv)
  153.  char **argv; {
  154.  int flg, i, j, k, print;
  155.  char *p, *cp, *getnext();
  156.  long nextadr;
  157.  struct ldesc *letter;
  158.  
  159.  /* get mailbox file name */
  160.  mkfilename( mfilename, maildir, mailbox );
  161.  
  162.  /* parse arg's */
  163.  for (; argc > 1; argv++, argc--) {
  164.   if ( argv[1][0] == '-' ) {
  165.    if ( argv[1][1] == 'f' ) {
  166.     if ( argc >= 3) {
  167.      if ( argv[2][0] == '=' )
  168.       mkfilename( mfilename, maildir, &argv[2][1] );
  169.      else
  170.       strcpy( mfilename, argv[2] );
  171.      argv++;
  172.      argc--;
  173.     }
  174.  
  175.    }
  176.    else if(argv[1][1 ]== 'p')
  177.     printonly++;
  178.    else {
  179.     fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
  180.     finis();
  181.    }
  182.   }
  183.   else
  184.    break;
  185.  }
  186.  
  187.  /* open real mailbox file */
  188. #ifdef Upgrade
  189.  if((rmailbox=FOPEN(mfilename, "r", 't')) == (FILE *)NULL)
  190. #else Upgrade
  191.  if((rmailbox=FOPEN(mfilename, "r", 'b')) == (FILE *)NULL)
  192. #endif Upgrade
  193.  {
  194.   fprintf(stdout, "No mail in %s.\n", mfilename);
  195.   return;
  196.  }
  197.  
  198.  /* open up tmp mailbox file */
  199.    if (( fmailbox = FOPEN( tmailbox, "w", 'b' )) == (FILE *)NULL ) {
  200.   fprintf( stderr, "mail: cannot open %s for writing\n", tmailbox );
  201.   finis();
  202.  }
  203.  
  204.  /* copy real mailbox file to tmp mailbox file */
  205.  letternum = 0 ;
  206.  nextadr = 0;
  207.  while(fgets(linebuf, LSIZE, rmailbox) != (char *)NULL) {
  208.   fputs(linebuf, fmailbox);
  209.  
  210.   if ( strncmp( linebuf, "From ", 5 ) == SAME ) {
  211.    letter = &letters[letternum++];
  212.    letter->from =
  213.    letter->subject =
  214.    letter->Date = -1L;
  215.    letter->adr = nextadr;
  216.    letter->delete = FALSE;
  217.    letter->size = 0L;
  218.   }else if ( strncmp( linebuf, "Date: ", 6 ) == SAME )
  219.    letter->Date = nextadr;
  220.   else if ( strncmp( linebuf, "From: ", 6 ) == SAME )
  221.    letter->from = nextadr;
  222.   else if ( strncmp( linebuf, "Subject: ", 9 ) == SAME )
  223.    letter->subject = nextadr;
  224.  
  225.   letter->size += 1L;
  226.   nextadr += strlen( linebuf );
  227.  }
  228.  
  229.  letters[letternum].adr = nextadr;   /* last plus 1 */
  230.  
  231.  /* close mailbox files */
  232.  fclose( rmailbox );
  233.  fclose( fmailbox );
  234.  
  235.  fmailbox = FOPEN( tmailbox, "r", 'b' );
  236.  
  237.  modified = 0;
  238.  
  239.  if ( printonly ) {
  240.   j = letternum;
  241.   while ( j > 0 ) {
  242.    pager( j );
  243.    j--;
  244.   }
  245.  
  246.   return;
  247.      }
  248.  
  249.  
  250.  printsub( -1 );
  251.  
  252.  i = letternum - 1;
  253.  while ( TRUE ) {
  254.  
  255.   if ( i < 0 )
  256.    i = 0;
  257.   if ( i >= letternum)
  258.    i = letternum - 1;
  259.   j = linvert( i );
  260.  
  261.   fprintf( stdout, "%d ? ", linvert( i ) );
  262.   
  263.   if ( fgets( resp, LSIZE, stdin) == (char *)NULL )
  264.    break;
  265.  
  266.   switch ( resp[0] ) {
  267.   default:
  268.    fprintf(stderr, "usage\n");
  269.   case '?':
  270.    print = 0;
  271.    fprintf( stderr, "q\tquit\n" );
  272.    fprintf( stderr, "x\texit\tmailbox restored\n" );
  273.    fprintf( stderr, "p\tprint message\n" );
  274.    fprintf( stderr, "s[file]\tsave message to a file (default =mbox)\n" );
  275.    fprintf( stderr, "w[file]\tsave message to a file (default =mbox) without headers\n" );
  276.    fprintf( stderr, "-\tprint last message\n" );
  277.    fprintf( stderr, "d\tdelete current message\n" );
  278.    fprintf( stderr, "+\tnext message (no delete)\n" );
  279.    fprintf( stderr, "f user\tforward current message to user\n" );
  280.    fprintf( stderr, "m user\tmail a message to user\n" );
  281.    fprintf( stderr, "g num\t set current message\n" );
  282.    break;
  283.   case '+':
  284.   case 'n':
  285.    i-- ;
  286.    break;
  287.   case 'g':
  288.    i = linvert( atoi( resp+2 ) );
  289.    break;
  290.   case '0':
  291.   case '1':
  292.   case '2':
  293.   case '3':
  294.   case '4':
  295.   case '5':
  296.   case '6':
  297.   case '7':
  298.   case '8':
  299.   case '9':
  300.    i = linvert( atoi( resp ) );
  301.    break;
  302.  
  303.   case 'x':
  304.    modified = 0;
  305.   case 'q':
  306.    goto donep;
  307.   case '\n':
  308.   case 'p':
  309.    pager( j );
  310.    break;
  311.   case '^':
  312.   case '-':
  313.    i++;
  314.    break;
  315.   case 'y':
  316.   case 'w':
  317.   case 's':
  318.    flg = 0;
  319.    if (resp[1] != '\n' && resp[1] != ' ') {
  320.     printf("illegal\n");
  321.     flg++;
  322.     print = 0;
  323.     continue;
  324.    }
  325.    if (strlen( resp ) == 1)
  326.     strcat( resp, " =mbox" );
  327.    for (p = resp+1; (p = getnext( &cp, p )) != (char *)NULL; ) {
  328.       if ( *cp == '=' )
  329.                        mkfilename( thefilename, maildir, ++cp );
  330.       else
  331.          strcpy( thefilename, cp );
  332.       fprintf( stderr, "%s to %s\n",
  333.         (resp[0] == 's') ? "Appending":"Writing", thefilename );
  334.       if (( fmailbag=FOPEN( thefilename, "a", 't' )) == (FILE *)NULL ) {
  335.          fprintf( stdout, "mail: cannot append to %s\n",
  336.                   thefilename );
  337.       flg++;
  338.       continue;
  339.       }
  340.       copymsg( j, fmailbag, resp[0]=='w' );
  341.       fclose( fmailbag );
  342.    }
  343.    if (flg)
  344.     print = 0;
  345.    else {
  346.     letters[j].delete = TRUE;
  347.     modified++;
  348.     i--;
  349.    }
  350.    break;
  351.   case 'm':
  352.    fprintf( stderr, "mail command not implemented yet!\n" );
  353.    break;
  354.   case 'f':
  355.    fprintf( stderr, "forward command not implemented yet!\n" );
  356.    break;
  357.    
  358.    /* NOTREACHED */
  359.    /* the problem with this code seems to be with closure
  360.     * of stdin to redirect input from mailbag. I would suggest
  361.     * recoding this program to allow an extra parameter to
  362.     * lmail, namely <stream> so that stdin is not futzed
  363.     * with. This will (of course) mess with the beautifully
  364.     * convoluted nature of this program and make it intelligible
  365.     * but I guess we can't have everything
  366.     * 8-). A. Shapiro 11/21/89
  367.     */
  368.    flg = 0;
  369.    if (resp[1] == '\n' || resp[1] == '\0') {
  370.     i++;
  371.     continue;
  372.    }
  373.    if (resp[1] != ' ') {
  374.     printf( "invalid command\n" );
  375.     flg++;
  376.     print = 0;
  377.     continue;
  378.    }
  379.  
  380.    sendmail(j, p);
  381.  
  382.    if (flg)
  383.     print = 0;
  384.    else {
  385.     letters[j].delete = TRUE;
  386.     modified++;
  387.     i++;
  388.    }
  389.    break;
  390.  
  391.   case 'd':
  392.    letters[j].delete = TRUE;
  393.    modified++;
  394.    i--;
  395.    if (resp[1] == 'q')
  396.     goto donep;
  397.    break;
  398.  
  399.   case 'h':
  400.    printsub( -1 );
  401.    break;
  402.  
  403.   case 'H':
  404.    printsub( i );
  405.    break;
  406.  
  407.   }
  408.  
  409.  }
  410.  donep:
  411.  if ( modified )
  412.   copyback();
  413. }
  414.  
  415. readaline( adr, line )
  416. long adr;
  417. char *line;
  418. {
  419.  char  buf[132];
  420.  char *cp;
  421.  
  422.  *line = '\0';
  423.  if ( adr != -1L )
  424.   if ( fseek( fmailbox, adr, 0 ) == 0 )
  425.    if ( fgets( buf, 132, fmailbox ) != (char *)NULL )
  426.     strcpy( line, buf );
  427.  
  428.  if ( (cp = index( line, '\n' ) ) != (char *) NULL)
  429.   *cp = '\0';
  430. }
  431.  
  432.  
  433. /*
  434. returnaddress()
  435. {
  436.  readaline( lp->from, linebuf );
  437.  if (
  438.   ( i = index( linebuf, '<' )) != 0 &&
  439.   ( k = index( linebuf, '>')) != 0 &&
  440.   ( k > i )
  441.   )
  442.  {
  443.   k -= i;
  444.   strncpy( from, linebuf[i], k );
  445.   from[k] = '\0';
  446.  }
  447.  else {
  448.  
  449.  
  450.  }
  451. }
  452. */
  453.  
  454. printsub( K )
  455. {
  456.  struct ldesc *ld;
  457.  int  j;
  458.  char from[132], subject[132], Date[132], line[132];
  459.  register char *sp, *dp, *lp, *tp;
  460.  int k, mink, maxk;
  461.  
  462.  pagereset();
  463.  
  464.  if ( K == -1 ) {
  465.   maxk = letternum -1;
  466.   mink = 0;
  467.  }
  468.  else
  469.   maxk = mink = K;
  470.  
  471.  for ( k = maxk ; k >= mink ; k-- ) {
  472.  
  473.   j = linvert( k );
  474.   ld = & letters[ j /*k*/];
  475.  
  476.    (void)strcpy(from, "unknown"); /* default to "unknown" */
  477.   readaline( ld->from, line );
  478.   if ( strlen( line ) > 0 ) {
  479.    /* Assume From: mailbox@site.domain */
  480.    /* get first usable stuff after From: */
  481.    sp = index( line, ':' ) + 1;
  482.  
  483.    /* do we have From: mailbox@site.domain ( Proper Name ) */
  484.    if ( ( ( tp = index( line, '(' )) != (char *) NULL &&
  485.      ( lp = index( line, ')')) != (char *) NULL  ) )
  486.     sp = ++tp;
  487.    /* or we may have From: Proper Name < mailbox@site.domain > */
  488.    else
  489.     lp = index( line, '<');
  490.  
  491.    if ( *lp == '<' || *lp == ')' )
  492.     --lp;
  493.  
  494.    /* if we didn't get either of the last two, just grab line */
  495.    if ( lp < sp || lp == (char *) NULL )
  496.     lp = line + strlen( line ) - 1;
  497.  
  498.    /*debugMsg("\PCheck isspace *sp");*/
  499.    while ( isspace( *sp ) ) sp++;
  500.  
  501.    /*debugMsg("\PCheck isspace *lp");*/
  502.    while ( isspace( *lp ) ) lp--;
  503.  
  504.    dp = from;
  505.    while ( sp <= lp ) *dp++ = *sp++;
  506.    *dp = '\0';
  507.   }
  508.  
  509.   /* Date: Wed May 13 23:59:53 1987 */
  510.    *Date = '\0'; /* default Date to null */
  511.   readaline( ld->Date, Date );
  512.   if ( strlen( Date ) > 0 ) {
  513.    sscanf( Date, "%*s %*s %s %s", line, subject );
  514.    sprintf( Date, "%s %s", line, subject );
  515.   }
  516.  
  517.   strcpy( subject, "--- no subject ---" );
  518.   readaline( ld->subject, line );
  519.   if ( strlen( line ) > 0 ) {
  520.    sp = line;
  521.    while ( !isspace( *sp ) ) sp++;
  522.    while ( isspace( *sp ) ) sp++;
  523.    strcpy( subject, sp );
  524.    }
  525.  
  526.   from[20] = '\0';
  527.   Date[6] = '\0';
  528.   subject[35] = '\0';
  529.  
  530.   sprintf( line, "%3d  %6s  %20s %35s (%6d)\n",
  531.       j, Date, from, subject, ld->size );
  532.   if ( pageline( line ) == TRUE )
  533.    break;
  534.  }
  535. }
  536.  
  537.  
  538. copyback()
  539. {
  540.  register i, n, c;
  541.  int new = 0;
  542.  
  543.  if (( fmailbag = FOPEN( mfilename, "w", 'b' )) == (FILE *)NULL ) {
  544.   fprintf (stderr, "mail: can't rewrite %s\n", mfilename );
  545.   finis();
  546.  }
  547.  n = 0;
  548.  for ( i = 0; i < letternum; i++ )
  549.   if ( letters[i].delete == FALSE ) {
  550.    copymsg( i, fmailbag, FALSE );
  551.    n++;
  552.   }
  553.  fclose (fmailbag );
  554. }
  555.  
  556.  
  557. /* copy a message
  558.    if noheaders true, don't copy header lines
  559. */
  560. copymsg( n, f, noheaders )
  561. FILE *f;
  562. {
  563.  long  bytes;
  564.  char buf[BUFSIZ];
  565.  
  566.  fseek( fmailbox, letters[n].adr, 0 );
  567.  bytes = letters[n+1].adr - letters[n].adr;
  568.  
  569.  while ( bytes > 0 && fgets( buf, BUFSIZ, fmailbox ) != (char *)NULL ) {
  570.   bytes -= strlen( buf );
  571.  
  572.   /* write line */
  573.   if ( !noheaders  )
  574.    fputs( buf, f );
  575.  
  576.   /* reset header */
  577.   if ( noheaders  && strcmp( buf, "\n") == SAME )
  578.    noheaders  = FALSE;
  579.  
  580.  }
  581. }
  582.  
  583. pager(n)
  584. {
  585.  long  bytes;
  586.  char buf[BUFSIZ];
  587.  
  588.  fseek( fmailbox, letters[n].adr, 0 );
  589.  bytes = letters[n+1].adr - letters[n].adr;
  590.  
  591.  pagereset();
  592.  while ( bytes > 0 && fgets( buf, BUFSIZ, fmailbox ) != (char *)NULL ) {
  593.   bytes -= strlen( buf );
  594.   if ( pageline( buf ) == TRUE )
  595.    break;
  596.  }
  597.  
  598.  pageline( "\n" );
  599. }
  600.  
  601. pagereset()
  602. {
  603.  PageCount = 0;
  604. }
  605.  
  606. pageline( s )
  607. char * s;
  608. {
  609.  char c;
  610.  
  611.  fputs( s, stdout );
  612.  if ( ++PageCount > 23 ) {
  613.   PageCount = 0;
  614.   c = get_one();
  615.   switch( c ) {
  616.   case 'q':
  617.   case 'Q':
  618.   case '\003':
  619.   case 'x':
  620.   case 'X':
  621.    return( TRUE );
  622.   }
  623.  }
  624.  return( FALSE );
  625. }
  626.  
  627. char *getnext( s, p )
  628. register char **s, *p;
  629. {
  630.  *s = (char *)NULL;
  631.  while ( *p == ' ' || *p == '\t' )
  632.   p++;
  633.  if ( *p == '\n' || *p == '\0' )
  634.   return( (char *)NULL );
  635.  *s = p;
  636.  while ( *p != ' ' && *p != '\t' && *p != '\n' && *p != '\0' )
  637.   *p++;
  638.  if ( *p != '\0' )
  639.   *p++ = '\0';
  640.  return(p);
  641. }
  642.  
  643. #ifdef MULTIFINDER
  644.  
  645. int Check_Events(long Sleep_Time)
  646. {
  647.      EventRecord Cur_Event;
  648.     (void) WaitNextEvent(updateMask, &Cur_Event, 0, (RgnHandle) NULL);
  649.     SystemTask();
  650. }
  651.  
  652. #endif
  653.